﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;

namespace DynamicProxy.Core.AutoProxy
{
    public class ProxyTypeCollection<T> : IEnumerable<ProxyType<T>> where T : IInterceptor, new()
    {
        #region 单例

        private static volatile ProxyTypeCollection<T> _instance = null;
        private static readonly object locker = new object();
        public static ProxyTypeCollection<T> Instance()
        {
            if (_instance == null)
            {
                lock (locker)
                {
                    if (_instance == null)
                    {
                        _instance = new ProxyTypeCollection<T>();
                    }
                }
            }
            return _instance;
        }

        #endregion

        private readonly Dictionary<Type, ProxyType<T>> _items;

        private ProxyTypeCollection()
        {
            _items = new Dictionary<Type, ProxyType<T>>();
        }

        #region Collection

        public ProxyType<T> this[Type name]
        {
            get
            {
                if (!_items.TryGetValue(name, out ProxyType<T> value))
                {
                    value = new ProxyType<T>(name);
                    this.Add(value);
                }
                return value;
            }
        }

        internal void Add(ProxyType<T> value)
        {
            var name = value.Type;
            if (!_items.TryGetValue(name, out ProxyType<T> p))
            {
                lock (locker)
                {
                    if (!_items.TryGetValue(name, out p))
                    {
                        _items.Add(name, value);
                    }
                }
            }
        }

        public bool ContainsKey(Type name) => _items.ContainsKey(name);

        public ICollection<Type> Names => _items.Keys;

        public int Count => _items.Count;

        #endregion

        public IEnumerator<ProxyType<T>> GetEnumerator()
        {
            foreach (var item in _items)
            {
                yield return item.Value;
            }
        }

        IEnumerator IEnumerable.GetEnumerator()
        {
            return _items.Values.GetEnumerator();
        }
    }
}
